Completed
Push — master ( d7f644...75d8ba )
by Andres
30s
created

angular.controller(ꞌct_redoxꞌ)   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
c 0
b 0
f 0
nc 1
dl 0
loc 3
rs 10
nop 2
1
/**
2
 redox
3
 Component that handles reduction/oxidation and ions.
4
5
 @namespace Components
6
 */
7
'use strict';
8
9
angular.module('game').component('redox', {
10
  templateUrl: 'views/redox.html',
11
  controller: 'ct_redox',
12
  controllerAs: 'ct'
13
});
14
15
angular.module('game').controller('ct_redox', ['state', 'data', 'visibility', 'util', 'format', 'reaction',
16
  function (state, data, visibility, util, format, reaction) {
17
    let ct = this;
18
    ct.state = state;
19
    ct.data = data;
20
    ct.util = util;
21
    ct.format = format;
22
    ct.reaction = reaction;
23
    ct.adjustAmount = [1, 10, 25, 100];
24
25
    ct.update = function(player) {
26
      processRedox(player);
27
      processElectronegativity(player);
28
    };
29
30
    function processRedox(player){
31
      for(let slot of player.element_slots){
32
        if(!slot){
33
          continue;
34
        }
35
        for (let redox of slot.redoxes) {
36
          if (!redox.resource || !redox.active || redox.from === redox.to) {
37
            continue;
38
          }
39
40
          let reactant = ct.generateName(redox.element, redox.from);
41
          let power = ct.redoxPower(player);
42
          let number = Math.min(power, player.resources[reactant].number);
43
          let react = ct.redoxReaction(redox);
44
45
          ct.reaction.react(number, react, player);
46
        }
47
      }
48
    }
49
50
    function processElectronegativity(player){
51
      for(let key in data.elements){
52
        let element = data.elements[key];
53
        if(element.electronegativity === 0){
54
          continue;
55
        }
56
        let ions = element.anions.concat(element.cations);
57
		    ions.push(element.main);
58
        for(let resource of ions){
59
          if(player.resources[resource].number === 0){
60
            continue;
61
          }
62
          let charge = data.resources[resource].charge || 0;
63
          let probabilities = probabilityDistribution(key, charge);
64
          for(let probKey in probabilities){
65
            if(probKey === charge){
66
              continue;
67
            }
68
            let production = Math.floor(probabilities[probKey]*player.resources[resource].number);
69
            if(production === 0){
70
              continue;
71
            }
72
            let react = ct.redoxReaction({
73
              element: key,
74
              from: charge,
75
              to: parseInt(probKey, 10)
76
            });
77
            // electronegativity is 'for free'
78
      			react.reactant.eV = 0;
79
            // FIXME: starvation should fix this
80
            if(react.reactant['e-']){
81
              production = Math.min(production, player.resources['e-'].number);
82
            }
83
            ct.reaction.react(production, react, player);
84
          }
85
        }
86
      }
87
    }
88
89
    function probabilityDistribution(element, charge){
90
    	let prob = {};
91
    	let start = -data.elements[element].electron_affinity.length;
92
    	let end = charge;
93
    	// lower than index, affected by negativity
94
    	rangeProbability(element, prob, start, end, 1, data.elements[element].negative_factor);
95
96
    	prob[charge] = 1;
97
98
    	start = charge+1;
99
    	end = data.elements[element].ionization_energy.length+1;
100
    	// lower than index, affected by positivity
101
    	rangeProbability(element, prob, start, end, -1, data.elements[element].positive_factor);
102
103
    	let sum = 0;
104
    	for(let i in prob){
105
    		sum += prob[i];
106
    	}
107
    	for(let i in prob){
108
    		prob[i] /= sum;
109
    	}
110
    	return prob;
111
    }
112
113
    function rangeProbability(element, prob, start, end, offset, factor){
114
    	for(let i = start; i < end; i++){
115
    		let difference = data.redox[element][i]-data.redox[element][i+offset];
116
    		if(difference <= 0){
117
    			difference = -difference;
118
    		}else{
119
    			difference = 1/difference;
120
    		}
121
    		prob[i] = Math.pow(data.constants.ELECTRONEGATIVITY_CHANCE,Math.abs(i))*factor*difference;
122
    	}
123
    }
124
125
    /* Calculates the redox power based on the redox upgrades */
126
    ct.redoxPower = function(player) {
127
      let level = player.global_upgrades_current.redox_bandwidth;
128
      let upgrade = data.global_upgrades.redox_bandwidth;
129
      let basePower = upgrade.power;
130
      let polynomial = upgrade.power_poly;
131
      return basePower * Math.floor(Math.pow(level, polynomial));
132
    };
133
134
    /* Writes a redox in the form of a reaction so that we can use the reaction
135
    service to process it */
136
    ct.redoxReaction = function (redox) {
137
      let reactant = ct.generateName(redox.element, redox.from);
138
      let product = ct.generateName(redox.element, redox.to);
139
      let energy = redoxEnergy(redox.from, redox.to, redox.element);
140
141
      let react = {
142
        'reactant': {},
143
        'product': {}
144
      };
145
146
      react.reactant[reactant] = 1;
147
      react.product[product] = 1;
148
      if (energy > 0) {
149
        react.reactant.eV = energy;
150
      } else if (energy < 0) {
151
        react.product.eV = -energy;
152
      }
153
154
      let electron = redox.from - redox.to;
155
      if (electron > 0) {
156
        react.reactant['e-'] = electron;
157
      } else if (electron < 0) {
158
        react.product['e-'] = -electron;
159
      }
160
161
      return react;
162
    };
163
164
    /* Calculates how much energy it takes to go from a redox level to another
165
    for a given element */
166
    function redoxEnergy(from, to, element) {
167
      let energyFrom = data.redox[element][from];
168
      let energyTo = data.redox[element][to];
169
      let energy = energyTo - energyFrom;
170
171
      return energy;
172
    }
173
174
    /* Generates the name of a ion, e.g. O3+ */
175
    ct.generateName = function (element, i) {
176
      if (i === 0) {
177
        return data.elements[element].main;
178
      }
179
      let postfix = '';
180
      if (Math.abs(i) > 1) {
181
        postfix = Math.abs(i);
182
      }
183
      postfix += getSign(i);
184
      let name = element + postfix;
185
      return name;
186
    };
187
188
    function getSign(number) {
189
      return number > 0 ? '+' : '-';
190
    }
191
192
    /* Calculates the number of redox slots based on the redox upgrades */
193
    ct.redoxSlots = function (player) {
194
      let level = player.global_upgrades.redox_slots;
195
      let upgrade = data.global_upgrades.redox_slots;
196
      let basePower = upgrade.power;
197
      let multiplier = upgrade.power_mult;
198
      return basePower * Math.floor(multiplier * level);
199
    };
200
201
    ct.redoxSize = function (player) {
202
      let size = 0;
203
      for(let slot of player.element_slots){
204
        if(!slot){
205
          continue;
206
        }
207
        size += slot.redoxes.length;
208
      }
209
      return size;
210
    };
211
212
    /* Adds a new redox to the player list */
213
    ct.addRedox = function (player, slot) {
214
      if(ct.redoxSize(player) >= ct.redoxSlots(player)){
215
        return;
216
      }
217
      slot.redoxes.push({
218
        resource: data.elements[slot.element].main,
219
        active: false,
220
        element: slot.element,
221
        from: 0,
222
        to: 1
223
      });
224
    };
225
226
    ct.removeRedox = function (slot, index) {
227
      slot.redoxes.splice(index, 1);
228
    };
229
230
    ct.visibleRedox = function(slot) {
231
      return slot.redoxes;
232
    };
233
234
    ct.adjustLevel = function(player, upgrade, amount){
235
      player.global_upgrades_current[upgrade] += amount;
236
      // We cap it between 1 and the current max level
237
      player.global_upgrades_current[upgrade] = Math.max(1, Math.min(player.global_upgrades_current[upgrade], player.global_upgrades[upgrade]));
238
    };
239
240
    state.registerUpdate('redox', ct.update);
241
  }
242
]);
243